前幾篇我們認識了 Pixel,知道一張圖片是由許多 Pixel 所組成。
每個 Pixel 又會記錄亮度或顏色的數值。
不過,這時候又冒出了另一個問題。
現實世界明明是連續的。
例如眼前的一片天空,它的顏色並不是突然從藍色變成白色,而是慢慢地漸層變化。
如果真的是這樣,那電腦又是怎麼把它存成一張圖片的?
其實在數位影像形成的過程中,有兩個很重要的步驟:
Sampling 可以理解成 從連續的世界中,決定要取多少個資料點。
假設現在有一條黑到白的漸層。
如果只取很少的點,圖片能保留的資訊就非常有限。
如果取很多點,漸層就會變得更平滑,也能保留更多細節。
放到影像裡,其實就是 Resolution 的概念。
例如:
解析度越高,代表取樣的 Pixel 越多。
先讀入一張圖片。
import cv2
import matplotlib.pyplot as plt
img = cv2.imread("dog.jpeg")
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
接著分別縮小成不同解析度,再放大回原本大小。
small = cv2.resize(img, (32, 32), interpolation=cv2.INTER_AREA)
middle = cv2.resize(img, (128, 128), interpolation=cv2.INTER_AREA)
small = cv2.resize(small, (img.shape[1], img.shape[0]), interpolation=cv2.INTER_NEAREST)
middle = cv2.resize(middle, (img.shape[1], img.shape[0]), interpolation=cv2.INTER_NEAREST)
最後比較三張圖片。
fig, ax = plt.subplots(1, 3, figsize=(12,4))
ax[0].imshow(img)
ax[0].set_title("Original")
ax[1].imshow(middle)
ax[1].set_title("128×128")
ax[2].imshow(small)
ax[2].set_title("32×32")
for a in ax:
a.axis("off")
plt.show()
看一下結果:

可以發現,當取樣點越少,圖片開始失去細節,甚至會看到明顯的馬賽克。
這就是 Sampling 太少造成的結果。
Sampling 解決的是有多少個 Pixel。
Quantization 則是在決定每個 Pixel 可以記錄多少種數值。
例如灰階圖片。
如果是 8-bit。
就可以表示:
0 ~ 255
總共有 256 個亮度。
但如果今天只有 2-bit。
就只能表示:
0
85
170
255
只有四種亮度。
因此即使 Pixel 一樣多,圖片看起來還是會變得不自然。
將原圖先轉灰階:
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
接著模擬只有 2-bit。
levels = 4
quantized = np.floor(gray / (256 / levels)) * (256 / levels)
quantized = quantized.astype(np.uint8)
顯示結果。
plt.figure(figsize=(10,4))
plt.subplot(1,2,1)
plt.imshow(gray, cmap="gray")
plt.title("Original")
plt.subplot(1,2,2)
plt.imshow(quantized, cmap="gray")
plt.title("2-bit")
plt.show()
結果:

可以發現。
原本平滑的漸層開始出現一層一層的色階。
這就是 Quantization 太少所造成的現象。
這種現象也常被稱為 Color Banding(色帶)。
雖然兩者都會影響圖片品質,但它們影響的地方其實不同。
| Sampling | Quantization |
|---|---|
| 決定 Pixel 數量 | 決定每個 Pixel 能表示多少亮度或顏色 |
| 對應解析度 | 對應 Bit Depth |
| 太少會失去細節 | 太少會產生色階、色帶 |
今天介紹了數位影像形成最重要的兩個概念。
從今天開始,我們已經知道:
下一篇開始,我們會正式進入數位影像處理常見的方法。
在介紹各種影像處理演算法之前,我們先來認識一個經常會出現的工具。
Histogram(直方圖)。
它可以幫助我們快速了解一張圖片的亮度分布,也是許多影像處理方法的重要基礎。